#include <sys/types.h>
#include <sys/time.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <assert.h>

#include "event.h"
#include "event_internal.h"
#include "evsignal.h"
#include "evutil.h"
#include "log.h"

struct event_base *evsignal_base = NULL;

static void evsignal_handler(int sig);

/* Callback for when the signal handler write a byte to our signaling socket */
static void
evsignal_cb(int fd, short what, void *arg)
{
	static char signals[1];
	ssize_t n;

	n = recv(fd, signals, sizeof(signals), 0);
	if (n == -1)
		event_err(1, "%s: read", __func__);
}

#define FD_CLOSEONEXEC(x) do { \
        if (fcntl(x, F_SETFD, 1) == -1) \
                event_warn("fcntl(%d, F_SETFD)", x); \
} while (0)
/*这个函数初始化了event_base中的evsignal_info结构体*/
int
evsignal_init(struct event_base *base)
{
	int i;

	 /*内部通信使用的UNIX域套接字,用于激活事件循环*/
	if (evutil_socketpair(
		    AF_UNIX, SOCK_STREAM, 0, base->sig.ev_signal_pair) == -1) {
		event_err(1, "%s: socketpair", __func__);
		return -1;
	}
	FD_CLOSEONEXEC(base->sig.ev_signal_pair[0]);
	FD_CLOSEONEXEC(base->sig.ev_signal_pair[1]);
	base->sig.sh_old = NULL;
	base->sig.sh_old_max = 0;
	base->sig.evsignal_caught = 0;
	memset(&base->sig.evsigcaught, 0, sizeof(sig_atomic_t)*NSIG);
	
	/*初始化信号链表*/
	for (i = 0; i < NSIG; ++i)
		TAILQ_INIT(&base->sig.evsigevents[i]);

	/*设置为非阻塞*/
        evutil_make_socket_nonblocking(base->sig.ev_signal_pair[0]);
	/*这里条用了event_set函数，这个函数的作用就是初始化了event，这里的event就是
	ev_signal_pair[1] 需要知道event_set函数的使用方法*/
	/*让base->sig.ev_signal这个event绑定到ev_signal_pair[1]这个套接字上，这个套接字上
	关注的事件均为可读，事件到达调用回调evsignal_cb，最后一个参数是传递给回调的参数
	evsignal_cb函数中之负责从ev_signal_pair[1]套接字上接受信息*/
	event_set(&base->sig.ev_signal, base->sig.ev_signal_pair[1],
		EV_READ | EV_PERSIST, evsignal_cb, &base->sig.ev_signal);

	base->sig.ev_signal.ev_base = base;
	base->sig.ev_signal.ev_flags |= EVLIST_INTERNAL;

	return 0;
}

/* Helper: set the signal handler for evsignal to handler in base, so that
 * we can restore the original handler when we clear the current one. */
int
_evsignal_set_handler(struct event_base *base,
		      int evsignal, void (*handler)(int))
{
	struct sigaction sa;
	struct evsignal_info *sig = &base->sig;
	void *p;

	/*
	 * resize saved signal handler array up to the highest signal number.
	 * a dynamic array is used to keep footprint on the low side.
	 */
	if (evsignal >= sig->sh_old_max) {
		int new_max = evsignal + 1;
		event_debug(("%s: evsignal (%d) >= sh_old_max (%d), resizing",
			    __func__, evsignal, sig->sh_old_max));
		p = realloc(sig->sh_old, new_max * sizeof(*sig->sh_old));
		if (p == NULL) {
			event_warn("realloc");
			return (-1);
		}

		memset((char *)p + sig->sh_old_max * sizeof(*sig->sh_old),
		    0, (new_max - sig->sh_old_max) * sizeof(*sig->sh_old));

		sig->sh_old_max = new_max;
		sig->sh_old = p;
	}

	/* allocate space for previous handler out of dynamic array */
	sig->sh_old[evsignal] = malloc(sizeof *sig->sh_old[evsignal]);
	if (sig->sh_old[evsignal] == NULL) {
		event_warn("malloc");
		return (-1);
	}

	/* save previous handler and setup new handler */
	memset(&sa, 0, sizeof(sa));
	sa.sa_handler = handler;
	sa.sa_flags |= SA_RESTART;
	sigfillset(&sa.sa_mask);

	if (sigaction(evsignal, &sa, sig->sh_old[evsignal]) == -1) {
		event_warn("sigaction");
		free(sig->sh_old[evsignal]);
		return (-1);
	}


	return (0);
}
/*添加信号的函数*/
int
evsignal_add(struct event *ev)
{
	int evsignal;
	struct event_base *base = ev->ev_base;
	struct evsignal_info *sig = &ev->ev_base->sig;
	/*如果这个时间发现是可读/可写，说明不是信号事件*/
	if (ev->ev_events & (EV_READ|EV_WRITE))
		event_errx(1, "%s: EV_SIGNAL incompatible use", __func__);
	/*获取信号值*/
	evsignal = EVENT_SIGNAL(ev);
	assert(evsignal >= 0 && evsignal < NSIG);
	/*如果这个信号所在的链表为空，说明此信号第一次被注册*/
	if (TAILQ_EMPTY(&sig->evsigevents[evsignal])) {
		event_debug(("%s: %p: changing signal handler", __func__, ev));
		/*这个函数就是使用了处理信号处理函数的部分，但是信号处理函数的回调只
		有一个evsigna_handler*/
		if (_evsignal_set_handler(
			    base, evsignal, evsignal_handler) == -1)
			return (-1);

		/* catch signals if they happen quickly */
		/*evsignal_base是全局变量*/
		evsignal_base = base;
		/*这里调用了event_add，但是这个event_add关注的是信号内部的socket，在这个
		socket注册的回调函数是读取套接字上的一个字节，为了激活信号的
		内部I／O事件*/
		if (!sig->ev_signal_added) {
			if (event_add(&sig->ev_signal, NULL))
				return (-1);
			/*ev_singal_added的值只在这里被修改，如果第一次地一个信号别添加，才会执行这里
			表示判断信号存在的内部I／O被添加到反应堆中*/
			sig->ev_signal_added = 1;
		}
	}

	/* multiple events may listen to the same signal */
	/*在信号链表中将这个信号event添加进去*/
	TAILQ_INSERT_TAIL(&sig->evsigevents[evsignal], ev, ev_signal_next);

	return (0);
}

int
_evsignal_restore_handler(struct event_base *base, int evsignal)
{
	int ret = 0;
	struct evsignal_info *sig = &base->sig;
	struct sigaction *sh;

	sh = sig->sh_old[evsignal];
	sig->sh_old[evsignal] = NULL;
	if (sigaction(evsignal, sh, NULL) == -1) {
		event_warn("sigaction");
		ret = -1;
	}
	free(sh);
	return ret;
}

int
evsignal_del(struct event *ev)
{
	struct event_base *base = ev->ev_base;
	struct evsignal_info *sig = &base->sig;
	int evsignal = EVENT_SIGNAL(ev);

	assert(evsignal >= 0 && evsignal < NSIG);

	/* multiple events may listen to the same signal */
	TAILQ_REMOVE(&sig->evsigevents[evsignal], ev, ev_signal_next);

	if (!TAILQ_EMPTY(&sig->evsigevents[evsignal]))
		return (0);

	event_debug(("%s: %p: restoring signal handler", __func__, ev));

	return (_evsignal_restore_handler(ev->ev_base, EVENT_SIGNAL(ev)));
}
/*这个是信号处理函数，当信号到达是，回调执行的就是这个函数，对于所有的信号都是执行这个函数
函数中最重要的就是send一个字节给evsigna_info结构体中的内置套接字，这样就可以是的epoll_wait
返回，返回以后再判断所监听的I／O事件被激活是属于哪类事件，如果是信号事件，再回调用户自定义
的回调函数，这样就可以将信号事件转化为I／O事件了*/
static void
evsignal_handler(int sig)
{
	int save_errno = errno;

	if (evsignal_base == NULL) {
		event_warn(
			"%s: received signal %d, but have no base configured",
			__func__, sig);
		return;
	}
	/*信号sig内激活的次说增加1
	修改信号被捕获的标志*/
	evsignal_base->sig.evsigcaught[sig]++;
	evsignal_base->sig.evsignal_caught = 1;


	signal(sig, evsignal_handler);


	/* Wake up our notification mechanism */
	/*唤醒epoll_wait，使其返回*/
	send(evsignal_base->sig.ev_signal_pair[0], "a", 1, 0);
	errno = save_errno;
}
/*这个函数的执行就是在上个函数send一个
字节结束后，使得epoll_wait返回，然后将到达的信号事件存放到激活队列中
在epoll_dispatch函数中的epoll_wait函数返回后，有可能是信号事件触发，可能需要执行这个函数
*/
void
evsignal_process(struct event_base *base)
{
	struct evsignal_info *sig = &base->sig;
	struct event *ev, *next_ev;
	sig_atomic_t ncalls;
	int i;
	/*修改信号捕获标志*/
	base->sig.evsignal_caught = 0;
	/*遍历所有的信号链表*/
	for (i = 1; i < NSIG; ++i) {
		ncalls = sig->evsigcaught[i];
		if (ncalls == 0)
			continue;
		sig->evsigcaught[i] -= ncalls;
		/*如果信号i事件到达，且别激发了ncalls次，将信号i所在的信号事件链表中的所有事件
		都添加到激活链表中*/
		for (ev = TAILQ_FIRST(&sig->evsigevents[i]);
		    ev != NULL; ev = next_ev) {
			next_ev = TAILQ_NEXT(ev, ev_signal_next);
			if (!(ev->ev_events & EV_PERSIST))
				event_del(ev);
			/*将某个事件添加到激活链表中
			@ev 表示操作的event
			@ EV_SIGNAL 表示当前event的状态
			@ncalls 这个event被触发的次数
			*/
			event_active(ev, EV_SIGNAL, ncalls);
		}

	}
}

void
evsignal_dealloc(struct event_base *base)
{
	int i = 0;
	if (base->sig.ev_signal_added) {
		event_del(&base->sig.ev_signal);
		base->sig.ev_signal_added = 0;
	}
	for (i = 0; i < NSIG; ++i) {
		if (i < base->sig.sh_old_max && base->sig.sh_old[i] != NULL)
			_evsignal_restore_handler(base, i);
	}

	EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[0]);
	base->sig.ev_signal_pair[0] = -1;
	EVUTIL_CLOSESOCKET(base->sig.ev_signal_pair[1]);
	base->sig.ev_signal_pair[1] = -1;
	base->sig.sh_old_max = 0;

	/* per index frees are handled in evsignal_del() */
	free(base->sig.sh_old);
}
